home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Info-Mac 3
/
Info_Mac_1994-01.iso
/
Development
/
Source
/
AutoBin Source
/
binhex.c
< prev
next >
Wrap
Text File
|
1993-12-09
|
14KB
|
507 lines
#define FILE_NUM 4
/* Copyright (c) 1990-1992 by the University of Illinois Board of Trustees */
/************************************************************************
* functions to convert files to binhex and back again
* much of this code is patterned after xbin by Dave Johnson, Brown University
* Some is lifted straight from xbin. Our thanks to Dave & Brown.
************************************************************************/
// this code was then lifted from eudora. mxm
// 12-9-93 made it stand alone and work with drop shell code. mxm
typedef unsigned char *UPtr;
typedef Handle UHandle;
#include <string.h>
#include "DSGlobals.h"
#define True 1
#define False 0
#define LDRef(h) (*h)
#define UL(h)
#define BINHEX_OPEN 5807
#define BUFFER_SIZE 4096
#define MEM_ERR 6417
#define BINHEX_READ 5811
#define NuHandle NewHandle
#define NuPtr NewPtr
#define SetHandleBig SetHandleSize
#define FILL(pb,name,vRef,dirId) do { \
(pb).ioNamePtr = name; \
(pb).ioVRefNum = vRef; \
(pb).ioDirID = dirId; \
} while (0)
Boolean DontTranslate; /* don't use translation tables */
Boolean CommandPeriod; /* has cmd-. been pressed lately? */
/************************************************************************
* Declarations for private routines
************************************************************************/
void comp_q_crc_out(unsigned short c);
short EncodeDataChar(Byte c, UPtr toSpot);
int BinHexFork(short refN, UHandle dataBuffer,short dataSize,
Handle codedBuffer,UPtr name);
/************************************************************************
* six to eight bit conversion table
************************************************************************/
Byte BinHexTable[64] = {
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x30, 0x31, 0x32,
0x33, 0x34, 0x35, 0x36, 0x38, 0x39, 0x40, 0x41,
0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x50, 0x51, 0x52,
0x53, 0x54, 0x55, 0x56, 0x58, 0x59, 0x5a, 0x5b,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x68,
0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x70, 0x71, 0x72 };
unsigned long CalcCrc;
Byte State86;
Byte SavedBits;
Byte LineLength;
#define LCODE(dc) codedSpot += EncodeDataChar(dc,*codedBuffer+codedSpot)
#define CODE(dc) do { \
LCODE(dc); \
if ((Byte)dc==(Byte)0x90) LCODE(0); \
comp_q_crc_out(dc); \
} while (0)
#define CODESHORT(ds) do {short copy=ds; UPtr cp=&ds; \
CODE(cp[0]); CODE(cp[1]);} while(0)
#define CODELONG(dl) do {long copy=dl; UPtr cp=&dl; \
CODE(cp[0]); CODE(cp[1]); CODE(cp[2]); CODE(cp[3]);} while(0)
short MyResolveAlias(short *vRef,long *dirId,UPtr name,Boolean *wasAlias);
short SendTrans(short lines ,Ptr buffptr,short buffsize);
void WriteZero(UPtr pointer,long size);
void WarnUser (short id,short code);
void ComposeRString (void );
void GetRString (void );
long GetRLong (long id);
short FSHOpen(UPtr name,short vRefN,long dirId,short *refN,short perm);
short RFHOpen(UPtr name,short vRefN,long dirId,short *refN,short perm);
void FileSystemError (short id,StringPtr name,short err);
short HGetFileInfo(short vRef,long dirId,UPtr name,HFileInfo *hfi);
int SendBinHex(short vRef,long dirId,UPtr name);
void PushProgress(StringPtr name);
void ByteProgress(StringPtr text,short start,long amount);
void PopProgress(StringPtr name);
//--------------------------------------------------------------------
void PushProgress(StringPtr name)
//--------------------------------------------------------------------
{
SetPort(gSplashScreen);
EraseRect(&gSplashScreen->portRect);
MoveTo(10,18);
DrawString(name);
}
//--------------------------------------------------------------------
void PopProgress(StringPtr name)
//--------------------------------------------------------------------
{
SetPort(gSplashScreen);
//EraseRect(&gSplashScreen->portRect);
MoveTo(10,38);
DrawString(name);
}
//--------------------------------------------------------------------
void ByteProgress(StringPtr text,short sub,long amount)
//--------------------------------------------------------------------
{
Str255 temp;
Rect r;
static long curamount;
if (amount!=0)
curamount = amount;
curamount += sub;
SetPort(gSplashScreen);
r = gSplashScreen->portRect;
r.top = 20;
r.bottom = 40;
EraseRect(&r);
MoveTo(10,38);
if (text)
DrawString(text);
NumToString(curamount,&temp);
r.top = 40;
r.bottom = 60;
EraseRect(&r);
MoveTo(10,58);
DrawString(temp);
}
//--------------------------------------------------------------------
short SendTrans(short lines ,Ptr buffptr,short buffsize)
//--------------------------------------------------------------------
{
short oe;
long count = buffsize;
oe = FSWrite(gRefNum,&count,buffptr);
return oe;
}
/**********************************************************************
* write zeroes over an area of memory
**********************************************************************/
void WriteZero(UPtr pointer,long size)
{
while (size--) *pointer++ = 0;
}
void WarnUser (short id,short code)
{
}
void ComposeRString (void)
{
}
void GetRString (void)
{
}
long GetRLong (long id)
{
return id;
}
/************************************************************************
* FSHOpen - like FSOpen, but takes a dirId and permissions, too.
************************************************************************/
short FSHOpen(UPtr name,short vRefN,long dirId,short *refN,short perm)
{
HIOParam pb;
int err;
Str255 newName;
//PCopy(newName,name);
BlockMove(name,newName,(*name) + 1);
if (err=MyResolveAlias(&vRefN,&dirId,newName,nil)) return(err);
pb.ioNamePtr = newName;
pb.ioVRefNum = vRefN;
pb.ioPermssn = perm;
pb.ioMisc = nil;
((HFileParam *)&pb)->ioDirID = dirId;
err = PBHOpen(&pb,False);
if (!err) *refN = pb.ioRefNum;
return(err);
}
/************************************************************************
* RFHOpen - like RFOpen, but with dirId and permissions
************************************************************************/
short RFHOpen(UPtr name,short vRefN,long dirId,short *refN,short perm)
{
HIOParam pb;
int err;
pb.ioCompletion = nil;
pb.ioNamePtr = name;
pb.ioVRefNum = vRefN;
pb.ioVersNum = 0;
pb.ioPermssn = perm;
pb.ioMisc = nil;
((HFileParam *)&pb)->ioDirID = dirId;
err = PBHOpenRF(&pb,False);
if (!err) *refN = pb.ioRefNum;
return(err);
}
//-----------------------------------------------------------------------
void FileSystemError (short id,StringPtr name,short err)
//-----------------------------------------------------------------------
{
ParamText(name,"\p","\p","\p");
Alert(1003,nil);
}
/************************************************************************
* MyResolveAlias - resolve an alias
************************************************************************/
short MyResolveAlias(short *vRef,long *dirId,UPtr name,Boolean *wasAlias)
{
}
//-----------------------------------------------------------------------
short HGetFileInfo(short vRef,long dirId,UPtr name,HFileInfo *hfi)
//-----------------------------------------------------------------------
{
short err,oe;
Str255 newName;
//PCopy(newName,name);
BlockMove(name,newName,(*name) + 1);
// if (err=MyResolveAlias(&vRef,&dirId,newName,nil)) return(err);
WriteZero(hfi,sizeof(*hfi));
FILL(*hfi,newName,vRef,dirId);
oe = PBHGetFInfo(hfi,False);
return(oe);
}
/************************************************************************
* SendBinHex - send a file as BinHex data
************************************************************************/
int SendBinHex(short vRef,long dirId,UPtr name)
{
short refN=0;
UHandle dataBuffer=nil;
UHandle codedBuffer=nil;
short dataSize;
short codedSize;
short codedSpot;
int err;
HFileInfo hfp;
Str255 scratch;
UPtr spot;
/*
* find the file, and get info
*/
err = HGetFileInfo(vRef,dirId,name,&hfp);
if (err) {FileSystemError(BINHEX_OPEN,name,err); goto done;}
/*
* allocate the buffers
*/
codedSize = GetRLong(BUFFER_SIZE);
dataSize = codedSize/3;
if (!(dataBuffer = (UHandle)NuHandle(dataSize)) || !(codedBuffer=(UHandle)NuHandle(codedSize)))
{WarnUser(MEM_ERR,MemError()); goto done;}
//ComposeRString(scratch,BINHEX_PROG_FMT,name);
PushProgress(name);
ByteProgress(scratch,0,hfp.ioFlLgLen+hfp.ioFlRLgLen);
/*
* send the header
*/
//GetRString(scratch,BINHEX_OUT);
strcpy(scratch,"\p\r(This file must be converted with BinHex 4.0)\r\r:");
if (err=SendTrans(1,scratch+1,*scratch)) goto done;
/*
* send the file information
*/
DontTranslate = True;
LineLength = 1;
State86 = CalcCrc = codedSpot = 0;
name[*name+1] = 0;
for (spot=name;*spot;spot++)
CODE(*spot);
CODE(0);
CODELONG(hfp.ioFlFndrInfo.fdType);
CODELONG(hfp.ioFlFndrInfo.fdCreator);
CODESHORT(hfp.ioFlFndrInfo.fdFlags);
CODELONG(hfp.ioFlLgLen);
CODELONG(hfp.ioFlRLgLen);
{
unsigned short tempCrc;
comp_q_crc_out(0);
comp_q_crc_out(0);
tempCrc = CalcCrc&0xffff;
CODESHORT(tempCrc);
CalcCrc = 0;
}
if (err=SendTrans(1,LDRef(codedBuffer),codedSpot)) goto done;
codedSpot = 0;
UL(codedBuffer);
/*
* data fork
*/
if (!vRef)
{FileSystemError(BINHEX_OPEN,name,0);goto done;}
if (err = FSHOpen(name,vRef,dirId,&refN,fsRdPerm))
{FileSystemError(BINHEX_OPEN,name,err); goto done;}
err = BinHexFork(refN,dataBuffer,dataSize,codedBuffer,name);
if (err) goto done;
/*
* resource fork
*/
if (refN) FSClose(refN);
refN = 0;
if (err = RFHOpen(name,vRef,dirId,&refN,fsRdPerm)){
FileSystemError(BINHEX_OPEN,name,err);
goto done;
}
err = BinHexFork(refN,dataBuffer,dataSize,codedBuffer,name);
if (err) goto done;
/*
* leftovers
*/
if (State86) CODE(0);
(*codedBuffer)[codedSpot++] = ':';
for (err=0;err<*NewLine;) {
(*codedBuffer)[codedSpot++] = NewLine[++err];
}
err = SendTrans(1,LDRef(codedBuffer),codedSpot);
done:
if (refN) FSClose(refN);
if (dataBuffer) DisposHandle(dataBuffer);
if (codedBuffer) DisposHandle(codedBuffer);
PopProgress("\pDone");
DontTranslate = False;
return(err);
}
/************************************************************************
* BinHexFork - send one fork of a file as BinHex data
************************************************************************/
int BinHexFork(short refN, UHandle dataBuffer,short dataSize,
Handle codedBuffer,UPtr name)
{
long dataEnd;
short codedSpot=0;
int err;
unsigned char *spot;
int errWas;
do
{
dataEnd = dataSize;
err = FSRead(refN,&dataEnd,LDRef(dataBuffer));
if (!err || err==eofErr)
{
errWas = err;
for (spot = *dataBuffer; spot<*dataBuffer+dataEnd; spot++)
CODE(*spot);
err=SendTrans(1,LDRef(codedBuffer),codedSpot);
UL(codedBuffer);
codedSpot = 0;
if (!err) err = errWas;
ByteProgress(nil,-dataEnd,0);
}
UL(dataBuffer);
if (err && err!=eofErr && !CommandPeriod)
FileSystemError(BINHEX_READ,name,err);
}
while (!err);
if (err==eofErr)
{
{
unsigned short tempCrc;
comp_q_crc_out(0);
comp_q_crc_out(0);
tempCrc = CalcCrc&0xffff;
CODESHORT(tempCrc);
CalcCrc = 0;
}
err=SendTrans(1,LDRef(codedBuffer),codedSpot);
UL(codedBuffer);
}
return(err==eofErr ? noErr : err);
}
/************************************************************************
* EncodeDataChar - encode an 8-bit data char into a six-bit buffer
* returns the number of valid encoded characters generated
************************************************************************/
short EncodeDataChar(Byte c, UPtr toSpot)
{
UPtr spotWas=toSpot;
UPtr nSpot;
#define ADDNEWLINE() do { \
LineLength = 0; \
for (nSpot=NewLine+1;nSpot<=NewLine+*NewLine;nSpot++) \
*toSpot++ = *nSpot; \
} while (0)
switch (State86++)
{
case 0:
*toSpot++ = BinHexTable[(c>>2)&0x3f];
SavedBits = (c&0x3)<<4;
if (++LineLength == 64) ADDNEWLINE();
break;
case 1:
*toSpot++ = BinHexTable[SavedBits | ((c>>4)&0xf)];
SavedBits = (c&0xf)<<2;
if (++LineLength == 64) ADDNEWLINE();
break;
case 2:
*toSpot++ = BinHexTable[SavedBits | ((c>>6)&0x3)];
if (++LineLength == 64) ADDNEWLINE();
*toSpot++ = BinHexTable[c&0x3f];
if (++LineLength == 64) ADDNEWLINE();
State86 = 0;
break;
}
return(toSpot-spotWas);
}
/************************************************************************
* comp_q_crc_out - lifted from xbin
************************************************************************/
#define BYTEMASK 0xff
#define BYTEBIT 0x100
#define WORDMASK 0xffff
#define WORDBIT 0x10000
#define CRCCONSTANT 0x1021
void comp_q_crc_out(unsigned short c)
{
register unsigned long temp = CalcCrc;
/* Never mind why I call it WOP... */
#define WOP { \
c <<= 1; \
if ((temp <<= 1) & WORDBIT) \
temp = (temp & WORDMASK) ^ CRCCONSTANT; \
temp ^= (c >> 8); \
c &= BYTEMASK; \
}
WOP;
WOP;
WOP;
WOP;
WOP;
WOP;
WOP;
WOP;
CalcCrc = temp;
}
//void xmain(void)
//{
//NewLine[0]=1;
//NewLine[1]=13;
//NewLine[2]=0;
//
// Create("\pTest binhex out",-1,'R*ch','TEXT');
// FSOpen("\pTest binhex out",-1,&gRefNum);
// SendBinHex(-1,0,"\pAUX:TestBinhex");
// FSClose(gRefNum);
//}
//